package cn.biplam.front.component.data.tree.nodeList;

import java.util.ArrayList;
import java.util.Map;

import cn.biplam.common.bean.sqlengine.Sql;
import cn.biplam.common.client.Database;
import cn.biplam.common.client.DbResource;
import cn.biplam.common.client.OperatorResult;
import cn.biplam.common.paramters.TreeParam;
import cn.biplam.common.paramters.ModelType.Model_Object_Type;
import cn.biplam.common.paramters.TreeParam.Index_Tree_Node_Type;
import cn.biplam.common.struc.BaseStruc.IndexTableStruc;
import cn.biplam.common.tools.TOOLS;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.KvMap;
import cn.biplam.common.wrapper.Result;
import cn.biplam.common.wrapper.UserInfo;
import cn.biplam.common.wrapper.treeFlat.PcNode;
import cn.biplam.common.wrapper.treeFlat.flat.FlatResult;
import cn.biplam.common.wrapper.treeFlat.flat.callback.OperatorTypeFilterCallback;
import cn.biplam.common.wrapper.treeFlat.pcTree.IndexPcTree;
import cn.biplam.front.callback.AnchorCallBack;
import cn.biplam.front.html.base.HtmlWindow;
import cn.biplam.front.template.control.rfFlowTable.RfFlowTable;
import cn.biplam.front.template.control.rfFlowTable.SummaryRfFlowTable;
import cn.biplam.front.template.control.rfFlowTable.callback.action.ActionCallback;

public abstract class IndexChildList {

	/** 树参数 */
	protected KvMap<String, String> treeParams;
	/** 索引表名称 */
	protected String tableName;
	//节点ID
	protected String nodeId;
	//树数据
	protected Result treeData;

	//应用系统路径
	protected String sHomeUrl;
	//用户信息
	protected UserInfo mUser;
	//页面ID
	protected String tablePageId;
	//父亲们字段名
	protected ArrayList<String> parentFieldNames;
	//父亲们名称字段名
	protected ArrayList<String> parentNameFieldNames;
	//父亲们名称字段名
	protected ArrayList<String> parentCnNameFieldNames;

	/** 按节点类型过滤回调器,返回的数据将按节点类型过滤 */
	protected OperatorTypeFilterCallback operatorTypeFilter;
	/** 显示汇总 */
	protected boolean showSummary = false;
	
	/**
	 * 
	 * @param sHomeUrl      应用系统路径
	 * @param mUser         用户
	 * @param tablePageId   树的targetID
	 * @param recordId      树节点记录ID
	 */
	public IndexChildList(
			String sHomeUrl,
			UserInfo mUser,
			String tablePageId,
			String recordId){
		this.nodeId = recordId;
		this.sHomeUrl = sHomeUrl;
		this.mUser = mUser;
		this.tablePageId = tablePageId;
	}

	/**
	 *  设置表名
	 * @param tableName  表名称
	 * @throws ErrorMessage
	 */
	public void setTableName(String tableName) throws ErrorMessage{
		this.tableName = tableName;
		if(tableName==null){
			throw new ErrorMessage("Table name is null at IndexTreeChildList!");
		}
	}
	
	
	/**
	 *  设置树参数
	 * @param params  设置树参数
	 * @throws ErrorMessage 
	 */
	public void setParams(KvMap<String, String> params) throws ErrorMessage{
		this.treeParams = params;
		setTableName(treeParams.getByKey(TreeParam.TABLE_NAME));
	}

	/**
	 *  设置节点操作类型过滤回调器<BR>
	 *  如果未设置过滤器为索引树节点的叶子节点
	 */
	public void setOperatorTypeFilterCallback(OperatorTypeFilterCallback callback){
		this.operatorTypeFilter = callback;
	}

	/**
	 *  设置显示汇总行
	 */
	public void showSummary(){
		this.showSummary = true;
	}
	
	/**
	 * @return 获取树平面化数据
	 */
	private void getData() throws ErrorMessage{
		//创建索引表树形节点
		IndexPcTree indexTree = new IndexPcTree(this.tableName);
		indexTree.setInclude(nodeId);
		PcNode nodeData = indexTree.get();
		//获取索引表平面化数据
		FlatResult result = new FlatResult(nodeData);
		result.setNodeIdField(IndexTableStruc.NODE_ID);
		result.setNodeNameField(IndexTableStruc.NODE_NAME);
		result.setParentFieldName(IndexTableStruc.NODE_PARENT);
		result.setOperatorTypeFieldName(IndexTableStruc.OPERATOR_TYPE);
		if(this.operatorTypeFilter==null){
			this.operatorTypeFilter = new IndexTableLeafOperatorFilter();
		}
		//设置节点过滤条件
		result.setOperatorTypeFilterCallback(this.operatorTypeFilter);
		this.treeData = result.getData();
		//获取平面化后父亲们字段名称
		this.parentFieldNames = result.getParentFieldNameList();
		this.parentNameFieldNames = result.getParentNameFieldNameList();
		this.parentCnNameFieldNames = result.getParentFieldCnNameList();
	}

	/**
	 *  绘制汇总表
	 * @return 汇总表表格
	 */
	private HtmlWindow drawTableWithSummary() throws ErrorMessage{
		SummaryRfFlowTable table = new SummaryRfFlowTable(
				sHomeUrl,
				mUser,
				tablePageId,
				new OperatorResult(treeData)
				);
		table.setHeight(610);
		table.setMainKey(IndexTableStruc.NODE_ID);
		for(int i=0;i<this.parentFieldNames.size();i++){
			String parentField = parentFieldNames.get(i);
			String parentFieldName = parentNameFieldNames.get(i);
			String parentCnName = parentCnNameFieldNames.get(i);
			table.putDimensionField(parentField, parentCnName,
					new AnchorCallBack(parentFieldName,null),
					getDrillAction(parentField));
		}
		table.putIndicateField(IndexTableStruc.NODE_ID, "表",
				new AnchorCallBack(IndexTableStruc.NODE_NAME,null),
				getDrillAction(null));
		//不含统计的行绘制
		table.processed();
		//获取维度值列表
		KvMap<String, String> dimValueList = table.getDemesionValueList();
		//设置汇总数据集
		table.setSummaryResult(queryIndexCount(dimValueList, 
				IndexTableStruc.NODE_ID,
				IndexTableStruc.NODE_PARENT));
		//根据维度值统计数据
		HtmlWindow win = table.get();
		return win;
	}
	
	/**
	 *  
	 * @return 按照维度表汇总数据
	 */
	private Result queryIndexCount(KvMap<String, String> dimValueList,
			String nodeIdField,
			String nodeParent) throws ErrorMessage{
		StringBuilder sp = new StringBuilder();
		StringBuilder inCondition = new StringBuilder();
		StringBuilder dimFields = new StringBuilder();
		int i = 0;
		for(Map.Entry<String, String> dimValue:dimValueList){
			String dim = dimValue.getKey();
			String value = dimValue.getValue();
			//查询维度字段
			dimFields.append("b."+dim);
			if(i<dimValueList.size()-1){
				dimFields.append(",");
			}
			//维度字段范围条件
			if(i==0){
				inCondition.append(" (");
			}else{
				inCondition.append(" or ");
			}
			inCondition.append(dim);
			inCondition.append(" in ");
			inCondition.append("(");
			inCondition.append(TOOLS.StringSplitToSingleQuote(value, ","));
			inCondition.append(")");
			if(i==dimValueList.size()-1){
				inCondition.append(")");
			}
			i++;
		}
		sp.append(" select ");
		sp.append(dimFields);
		sp.append(",");
		//被统计字段
		sp.append("count(1) "+nodeIdField);
		sp.append(" from ");
		sp.append(this.tableName);
		sp.append(" a join ");
		sp.append(this.tableName+"_Flat");
		sp.append(" b on a."+nodeIdField+"="+"b."+nodeIdField);
		sp.append(" where ");
		sp.append("a.operator_type='"+Model_Object_Type.TABLE.toString()+"'");
		sp.append(" and ");
		sp.append(inCondition);
		sp.append(" group by ");
		sp.append(dimFields);
		sp.append(" order by ");
		sp.append(dimFields);
		//执行查询
		Database db = new Database(new DbResource(),mUser.getUserID(),null);
		try{
			return db.executeSelect(new Sql(sp.toString()));
		}catch (Exception e) {
			StringBuilder erroi = new StringBuilder();
			erroi.append("父子表转换树,数据查询错误:");
			erroi.append(e.getMessage());
			throw new ErrorMessage(erroi.toString());
		}
	}
	
	/**
	 *  绘制表格
	 * @throws ErrorMessage
	 */
	private HtmlWindow drawTable() throws ErrorMessage{
		RfFlowTable table = new RfFlowTable(sHomeUrl,
				mUser,
				tablePageId,
				new OperatorResult(treeData));
		table.setHeight(610);
		table.setMainKey(IndexTableStruc.NODE_ID);
		for(int i=0;i<this.parentFieldNames.size();i++){
			String parentField = parentFieldNames.get(i);
			String parentFieldName = parentNameFieldNames.get(i);
			String parentCnName = parentCnNameFieldNames.get(i);
			table.putField(parentFieldName, parentCnName,
					new AnchorCallBack(parentFieldName,null),
					getDrillAction(parentField));
			table.setRemoveRepeat(parentFieldName);//设置剔重
		}
		table.putField(IndexTableStruc.NODE_NAME, " ",
				new AnchorCallBack(IndexTableStruc.NODE_NAME,null),
				getDrillAction(null));
		HtmlWindow win = table.get();
		return win;
	}

	/**
	 *  
	 * @return 钻取动作回调器
	 */
	protected abstract ActionCallback getDrillAction(String fieldName);
	
	/**
	 *  获取索引表指定节点下的所有子节点层次关系表格
	 * @return 索引表指定节点下的所有子节点层次关系表格
	 * @throws ErrorMessage 
	 */
	public HtmlWindow get() throws ErrorMessage{
		this.getData();
		if(this.showSummary){
			return this.drawTableWithSummary();
		}else{
			return this.drawTable();
		}
	}

	/**
	 * 索引表叶子节点类型过滤器
	 */
	class IndexTableLeafOperatorFilter implements OperatorTypeFilterCallback{

		public boolean isFilter(String operatorType) {
			if(operatorType.equals(Index_Tree_Node_Type.OTHER.toString())){
				return false;//未被过滤
			}else{
				return true;//被过滤
			}
		}
	}
	
}
